﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Universe = FRAFV.Geo.Universe;

namespace SkyData
{
	[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
	public class BinBlockAttribute: Attribute
	{
		public string Format { get; set; }
	}

	[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
	public class BinDataAttribute: Attribute
	{
		public string Format { get; set; }
		public string Checker { get; set; }
	}

	[BinBlock(Format = "stars")]
	[BinBlock(Format = "starnames")]
	public class Star: IXmlSerializable
	{
		private Universe.Star star = new Universe.Star();
		private int id;

		System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
		{
			return null;
		}

		void IXmlSerializable.ReadXml(XmlReader reader)
		{
			var ser = new XmlSerializer(typeof(Universe.Star));
			this.star = (Universe.Star)ser.Deserialize(reader);
		}

		void IXmlSerializable.WriteXml(XmlWriter writer)
		{
			var ser = new XmlSerializer(typeof(Universe.Star));
			ser.Serialize(writer, this.star);
		}

		static double[] StarBV = new double[]
		{
			//#FFFFFF
			-0.40, //#9BB2FF; B-V = -0.40; Teff = 113017
			-0.35, //#9EB5FF; B-V = -0.35; Teff = 56701
			-0.30, //#A3B9FF; B-V = -0.30; Teff = 33605
			-0.25, //#AABFFF; B-V = -0.25; Teff = 22695
			-0.20, //#B2C5FF; B-V = -0.20; Teff = 16954
			-0.15, //#BBCCFF; B-V = -0.15; Teff = 13674
			-0.10, //#C4D2FF; B-V = -0.10; Teff = 11677
			-0.05, //#CCD8FF; B-V = -0.05; Teff = 10395
			0.00, //#D3DDFF; B-V = -0.00; Teff = 9531
			0.05, //#DAE2FF; B-V = 0.05; Teff = 8917
			0.10, //#DFE5FF; B-V = 0.10; Teff = 8455
			0.15, //#E4E9FF; B-V = 0.15; Teff = 8084
			0.20, //#E9ECFF; B-V = 0.20; Teff = 7767
			0.25, //#EEEFFF; B-V = 0.25; Teff = 7483
			0.30, //#F3F2FF; B-V = 0.30; Teff = 7218
			0.35, //#F8F6FF; B-V = 0.35; Teff = 6967
			0.40, //#FEF9FF; B-V = 0.40; Teff = 6728
			0.45, //#FFF9FB; B-V = 0.45; Teff = 6500
			0.50, //#FFF7F5; B-V = 0.50; Teff = 6285
			0.55, //#FFF5EF; B-V = 0.55; Teff = 6082
			0.60, //#FFF3EA; B-V = 0.60; Teff = 5895
			0.65, //#FFF1E5; B-V = 0.65; Teff = 5722
			0.70, //#FFEFE0; B-V = 0.70; Teff = 5563
			0.75, //#FFEDDB; B-V = 0.75; Teff = 5418
			0.80, //#FFEBD6; B-V = 0.80; Teff = 5286
			0.85, //#FFE9D2; B-V = 0.85; Teff = 5164
			0.90, //#FFE8CE; B-V = 0.90; Teff = 5052
			0.95, //#FFE6CA; B-V = 0.95; Teff = 4948
			1.00, //#FFE5C6; B-V = 1.00; Teff = 4849
			1.05, //#FFE3C3; B-V = 1.05; Teff = 4755
			1.10, //#FFE2BF; B-V = 1.10; Teff = 4664
			1.15, //#FFE0BB; B-V = 1.15; Teff = 4576
			1.20, //#FFDFB8; B-V = 1.20; Teff = 4489
			1.25, //#FFDDB4; B-V = 1.25; Teff = 4405
			1.30, //#FFDBB0; B-V = 1.30; Teff = 4322
			1.35, //#FFDAAD; B-V = 1.35; Teff = 4241
			1.40, //#FFD8A9; B-V = 1.40; Teff = 4159
			1.45, //#FFD6A5; B-V = 1.45; Teff = 4076
			1.50, //#FFD5A1; B-V = 1.50; Teff = 3989
			1.55, //#FFD29C; B-V = 1.55; Teff = 3892
			1.60, //#FFD096; B-V = 1.60; Teff = 3779
			1.65, //#FFCC8F; B-V = 1.65; Teff = 3640
			1.70, //#FFC885; B-V = 1.70; Teff = 3463
			1.75, //#FFC178; B-V = 1.75; Teff = 3234
			1.80, //#FFB765; B-V = 1.80; Teff = 2942
			1.85, //#FFA94B; B-V = 1.85; Teff = 2579
			1.90, //#FF9523; B-V = 1.90; Teff = 2150
			1.95, //#FF7B00; B-V = 1.95; Teff = 1675
			2.00, //#FF5200; B-V = 2.00; Teff = 1195
		};

		static int[] StarColor = new int[]
		{
			0xFFFFFF,
			0x9BB2FF, //B-V = -0.40; Teff = 113017
			0x9EB5FF, //B-V = -0.35; Teff = 56701
			0xA3B9FF, //B-V = -0.30; Teff = 33605
			0xAABFFF, //B-V = -0.25; Teff = 22695
			0xB2C5FF, //B-V = -0.20; Teff = 16954
			0xBBCCFF, //B-V = -0.15; Teff = 13674
			0xC4D2FF, //B-V = -0.10; Teff = 11677
			0xCCD8FF, //B-V = -0.05; Teff = 10395
			0xD3DDFF, //B-V = -0.00; Teff = 9531
			0xDAE2FF, //B-V = 0.05; Teff = 8917
			0xDFE5FF, //B-V = 0.10; Teff = 8455
			0xE4E9FF, //B-V = 0.15; Teff = 8084
			0xE9ECFF, //B-V = 0.20; Teff = 7767
			0xEEEFFF, //B-V = 0.25; Teff = 7483
			0xF3F2FF, //B-V = 0.30; Teff = 7218
			0xF8F6FF, //B-V = 0.35; Teff = 6967
			0xFEF9FF, //B-V = 0.40; Teff = 6728
			0xFFF9FB, //B-V = 0.45; Teff = 6500
			0xFFF7F5, //B-V = 0.50; Teff = 6285
			0xFFF5EF, //B-V = 0.55; Teff = 6082
			0xFFF3EA, //B-V = 0.60; Teff = 5895
			0xFFF1E5, //B-V = 0.65; Teff = 5722
			0xFFEFE0, //B-V = 0.70; Teff = 5563
			0xFFEDDB, //B-V = 0.75; Teff = 5418
			0xFFEBD6, //B-V = 0.80; Teff = 5286
			0xFFE9D2, //B-V = 0.85; Teff = 5164
			0xFFE8CE, //B-V = 0.90; Teff = 5052
			0xFFE6CA, //B-V = 0.95; Teff = 4948
			0xFFE5C6, //B-V = 1.00; Teff = 4849
			0xFFE3C3, //B-V = 1.05; Teff = 4755
			0xFFE2BF, //B-V = 1.10; Teff = 4664
			0xFFE0BB, //B-V = 1.15; Teff = 4576
			0xFFDFB8, //B-V = 1.20; Teff = 4489
			0xFFDDB4, //B-V = 1.25; Teff = 4405
			0xFFDBB0, //B-V = 1.30; Teff = 4322
			0xFFDAAD, //B-V = 1.35; Teff = 4241
			0xFFD8A9, //B-V = 1.40; Teff = 4159
			0xFFD6A5, //B-V = 1.45; Teff = 4076
			0xFFD5A1, //B-V = 1.50; Teff = 3989
			0xFFD29C, //B-V = 1.55; Teff = 3892
			0xFFD096, //B-V = 1.60; Teff = 3779
			0xFFCC8F, //B-V = 1.65; Teff = 3640
			0xFFC885, //B-V = 1.70; Teff = 3463
			0xFFC178, //B-V = 1.75; Teff = 3234
			0xFFB765, //B-V = 1.80; Teff = 2942
			0xFFA94B, //B-V = 1.85; Teff = 2579
			0xFF9523, //B-V = 1.90; Teff = 2150
			0xFF7B00, //B-V = 1.95; Teff = 1675
			0xFF5200, //B-V = 2.00; Teff = 1195
		};

		[BinData(Format = "stars")]
		public float Magnitude
		{
			get { return (float)this.star.Magnitude; }
			set { this.star.Magnitude = value; }
		}

		[BinData(Format = "stars")]
		public float RA
		{
			get { return (float)this.star.RightAscension; }
			set { this.star.RightAscension = value; }
		}

		[BinData(Format = "stars")]
		public float Dec
		{
			get { return (float)this.star.Declination; }
			set { this.star.Declination = value; }
		}

		[BinData(Format = "stars")]
		public int ID
		{
			get
			{
				return this.star.ID.GetValue(0);
			}
			set
			{
				this.id = value;
			}
		}

		[BinData(Format = "stars")]
		public byte Catalog
		{
			get
			{
				return (byte)this.star.ID.GetKey(0);
			}
			set
			{
				this.star.ID.Insert(0, (Universe.Star.StarCatalog)value, this.id);
			}
		}

		[BinData(Format = "stars")]
		public byte Color
		{
			get
			{
				if (!this.star.BV.HasValue)
					return 0;
				int index = Array.IndexOf(StarBV, this.star.BV.Value);
				if (index < 0)
					throw new IndexOutOfRangeException("BV");
				return (byte)(index + 1);
			}
			set
			{
				this.star.BV = value > 0 ? (double?)StarBV[value - 1] : null;
				this.star.Color = System.Drawing.Color.FromArgb(StarColor[value]);
			}
		}

		[BinData(Format = "starnames")]
		public bool HasName
		{
			get { return this.Name != null; }
		}

		[BinData(Checker = "HasName", Format = "starnames")]
		public string Name
		{
			get { return this.star.Name["ru"] ?? this.star.Name.GetValue(0); }
			set { this.star.Name["ru"] = value; }
		}

		[BinData(Format = "starnames")]
		public bool HasBayerFlamsted
		{
			get { return this.BayerFlamsted != null; }
		}

		[BinData(Checker = "HasBayerFlamsted", Format = "starnames")]
		public string BayerFlamsted
		{
			get { return this.star.Code[Universe.Star.StarCatalog.BSC]; }
			set { this.star.Code[Universe.Star.StarCatalog.BSC] = value; }
		}
	}
}
